package cn.yiyuan.car.service.impl;

import cn.yiyuan.base.config.HighlightResultMapper;
import cn.yiyuan.base.until.PageInfo;
import cn.yiyuan.car.dto.Cardto;
import cn.yiyuan.car.dto.vo.BuckeVo;
import cn.yiyuan.car.query.CarDocQuery;
import cn.yiyuan.car.service.ICarDocService;
import org.apache.commons.lang3.time.DateUtils;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.BucketOrder;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @user m
 * @project Car_mall_system
 * @date 2024-01-08
 * @package cn.yiyuan.car.service.impl
 */
@Service
public class CarDocServiceImpl implements ICarDocService {

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Autowired
    private HighlightResultMapper highlightResultMapper;

    @Override
    public PageInfo queryPage(CarDocQuery query) {
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        //1构建一个组合查询对象
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        //-------------------DSL查询-------------------
        /*
             1构造查询条件
             使用对象，判断前端传值（关键字）是否为空
         */
        if (Objects.nonNull(query.getKeyword())){
            MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("title",query.getKeyword());//匹配查询，入参为字段+值
            boolQueryBuilder.must(matchQueryBuilder);
        }
        // -------------------DSL过滤-------------------
        //价格搜索
        if (Objects.nonNull(query.getPriceMax())){
            RangeQueryBuilder costprice = QueryBuilders.rangeQuery("costprice").lte(query.getPriceMax());
            boolQueryBuilder.filter(costprice);
        }
        if (Objects.nonNull(query.getPriceMin())){
            RangeQueryBuilder costprice = QueryBuilders.rangeQuery("costprice").gte(query.getPriceMin());
            boolQueryBuilder.filter(costprice);
        }

        // -------------------车龄查询-------------------
        //carAgeMax  计算车龄以前的时间
        if (Objects.nonNull(query.getCarAgeMax())){
            long time = DateUtils.addYears(new Date(), 0 - query.getCarAgeMax()).getTime();
            RangeQueryBuilder reigstertime = QueryBuilders.rangeQuery("reigstertime").gte(time);
            boolQueryBuilder.filter(reigstertime);
        }

        //carAgeMin
        if (Objects.nonNull(query.getCarAgeMin())){
            long time = DateUtils.addYears(new Date(), 0 - query.getCarAgeMin()).getTime();
            RangeQueryBuilder reigstertime = QueryBuilders.rangeQuery("reigstertime").lte(time);
            boolQueryBuilder.filter(reigstertime);
        }

        // -------------------超值&急售&准新&可迁全国查询-------------------
        if (Objects.nonNull(query.getCosteffective())){
            TermQueryBuilder costeffective = QueryBuilders.termQuery("costeffective", query.getCosteffective());
            boolQueryBuilder.filter(costeffective);
        }
        if (Objects.nonNull(query.getRushsale())){
            TermQueryBuilder costeffective = QueryBuilders.termQuery("rushsale", query.getRushsale());
            boolQueryBuilder.filter(costeffective);
        }
        if (Objects.nonNull(query.getQuasinewcar())){
            TermQueryBuilder costeffective = QueryBuilders.termQuery("quasinewcar", query.getQuasinewcar());
            boolQueryBuilder.filter(costeffective);
        }
        if (Objects.nonNull(query.getTransitivecountry())){
            TermQueryBuilder costeffective = QueryBuilders.termQuery("transitivecountry", query.getTransitivecountry());
            boolQueryBuilder.filter(costeffective);
        }
        // -------------------排序条件-------------------
        if (Objects.nonNull(query.getOrderField())){ //orderField 排序字段  orderType 排序类型
            queryBuilder.withSort(new FieldSortBuilder(query.getOrderField())
                    .order(query.getOrderType().equals("ASC")? SortOrder.ASC:SortOrder.DESC));

        }


        // -------------------添加地理位置查询-------------------
        if (Objects.nonNull(query.getLat())&& Objects.nonNull(query.getLng())&& Objects.nonNull(query.getDistance())){
            //1.距离范围的查询构建
            GeoDistanceQueryBuilder shopPointBuilder = QueryBuilders.geoDistanceQuery("shopPoint");//es里面用来存储金纬度对象的字段名字
            //把用户的经纬度设置到查询对象
            shopPointBuilder.point(query.getLat(),query.getLng());
            //2.设置要查询的距离范围
            shopPointBuilder.distance(query.getDistance(), DistanceUnit.KILOMETERS);
            //3.添加查询条件
            boolQueryBuilder.filter(shopPointBuilder);
        }

        // -------------------关键字高亮-------------------
        HighlightBuilder.Field field = new HighlightBuilder.Field("title");
        field.preTags("<span style='color:red'>"); //开始标签
        field.postTags("</span>");                  //结束标签
        queryBuilder.withHighlightFields(field);

        // -------------------聚合查询-------------------
        TermsAggregationBuilder aggregationBuilder = AggregationBuilders.terms("brandBukets").field("brand").order(BucketOrder.count(false)).size(50);
        TermsAggregationBuilder shopNameBuilder = AggregationBuilders.terms("shopNameBukets").field("shopName").order(BucketOrder.count(false)).size(50);
        queryBuilder.addAggregation(aggregationBuilder);
        queryBuilder.addAggregation(shopNameBuilder);
        // -------------------添加分页-------------------
        // -------------------添加分页-------------------
        queryBuilder.withPageable(PageRequest.of(query.getCurrentpage()-1,query.getPageSize()));
        //2添加查询条件
        queryBuilder.withQuery(boolQueryBuilder);

        AggregatedPage<Cardto> docPage = elasticsearchRestTemplate.queryForPage(queryBuilder.build(),Cardto.class, this.highlightResultMapper);
        // -------------------处理聚合结果集-------------------
        List<Aggregation>aggregations = docPage.getAggregations().asList();
        //定义一个map 用来封装返回的数据
        Map<String,List<BuckeVo>> map = new HashMap<>();


        aggregations.forEach(aggregation ->{
            //每一个buckets统计结果
            ParsedStringTerms parsedStringTerms = (ParsedStringTerms) aggregation;
            //统计的名字
            /**
             * [{"key" 宝马，"doc_count"：数据总数}]    [{"key" 宝骏，"doc_count"：数据总数}]
             */
            List<? extends Terms.Bucket> buckets =  parsedStringTerms.getBuckets();
            //new一个ArrayList来装
            List<BuckeVo> list = new ArrayList<>();
            //key宝马
            buckets.forEach(bucket -> {
                // key 宝马                    数量
                BuckeVo buckeVo = new BuckeVo(bucket.getKeyAsString(), bucket.getDocCount());
                list.add(buckeVo);

            });
            map.put(aggregation.getName(),list);
        });



        //获取命中的总页数
        long total = docPage.getTotalElements();
        //获取命中的数据
        List<Cardto> content = docPage.getContent();

        return new PageInfo<>(total,content,map);
    }
}
